CS498PS - Lab 2: Filter Design and Usage

Ching-Hua Yu (cyu17)

For this lab you will learn how to design some simple filters and how to apply them to solve some common audio problems. Python’s scipy.signal package has an extensive set of commands to help you design filters (firwin, firwin2, butter, cheby1, cheby2, ellip, …), so there is no shortage of options.

Part 1: When to use what

There will be four cases to this part, each requiring a different type of filter to address a problem in a recording. The input recordings are:

For each case do the following:

  • Plot the spectrogram of the given sound and identify the problem
  • Describe what kind of filter will address this problem and why
  • Design an FIR filter using scipy.signal.firwin() and/or scipy.signal.firwin2()
  • Design an FIR filter using the formulas in my slides (i.e. do not use scipy.signal)
  • Design an IIR Butterworth filter using scipy.signal's routines
  • Show a plot comparing the response of all the filters (hint: scipy.signal.freqz)
  • Plot spectrograms of the filtered recordings and compare with the input to show that it fixed the problem
  • Play the filtered sounds so that we can hear how well it works

Make some observations on how the results differ between an FIR and IIR filter and try to find the best possible filter size/type/parameters to produce the best result. Show results under various parameters (e.g. filter length) and make some plots that demonstrate the effects of these parameters. Most importantly, try to get a sense of how these design choices impact audible quality. Being able to listen at a sound and identify what’s wrong and how to fix it is a big part of audio processing.

Hint: To apply an FIR filter you can use scipy.signal.convolve, to apply an IIR filter (or an FIR) you can use scipy,signal.lfilter.

First, observe case1.wav contains high frequency noise, and from spectrogram, we can estimate the cutoff frequency which is around 6000Hz. Hence we apply a low-pass filter. Due to the limited boundary of filters, we apply a kaiser windom to make the filtering smoother.

case1 sound
case1 fixed

Second, case2.wav also contains high frequency noise, and from spectrogram, we can estimate the cutoff frequency which is around 1800Hz. Hence we apply a low-pass filter.

case2 sound
case2 fixed

Third, case3.wav contains low frequency noise (the thunder sound), and from spectrogram, we can estimate the cutoff frequency which is around 2000Hz. Hence we apply a high-pass filter.

case3 sound
case3 fixed

case4.wav contains Morse code and environment noise. Observe that the sound Morse code sounds are ranged in certain frequency bands so we apply bass-pass filter. Particularly, from spectrogram, we can see the morse code sound mainly appears in two separate ranges. Hence including both of these ranges can retain the original sound as good as possible.

case4 sound
case4 fixed

Next, we try to use sinc function to define filter directly. Take a low-pass filter in case1.wav for experiment as below

case1 sound
case1 fixed

Then we try IIR filter (using scipy.signal.iirdesign) and do experiment on case1.wav again.

case1 sound
case1 fixed

Part 2. Designing a simple equalizer

For this part we will design a simple graphic equalizer. We will do so using a more straightforward approach as opposed to a bank of filters as discussed in class.

We want to make an equalizer which contains six bands with center frequencies at 100Hz, 200Hz, 400Hz, 800Hz, 1600Hz and 3200Hz. Your equalizer function will take two inputs, one for the input sound and a 6-element gain vector that will indicate how much to boost or suppress each frequency band. Use the scipy.signal.firwin2 function to design a filter that has the desired characteristics. For various settings of the gain vector, use the scipy.signal.freqz command to plot the response of the filter and verify that it behaves as indicated. Experiment with various filter lengths and see which works best.

Once you figure that out, design a graphic equalizer with as many bands as you like (and arbitrary center frequencies as well), and use it to solve the problems in part 1 again. The only thing that should be different in the EQ for each recording should be the gains for each band. Play the output sounds, and show the spectrograms, see how they compare with your previous solutions.

Optional extra credit (+1pt): Use ipywidgets to make intective sliders and process an audio stream and play it from the speakers in real-time (either from mic input, or just stream audio from disk).

We implement an equalizer function with six fixed bands 100Hz, 200Hz, 400Hz, 800Hz, 1600Hz, 3200Hz, where the input is a 6-element gain vector (in [0,1]) and the Nyquist rate. A low pass filter can be approximated as gain = [1,1,1,1,0,0] so that the cutoff is around 800Hz.

Then we try to use the equalizer to simulate a low-pass filter for case1.wav The cutoff freqency of the low-pass filter we used for case1 was 6kHZ. Here we can only set up to 3200Hz, but well, it still filters noise and retains most speech freqnecy.

case1 sound
case1 fixed